package com.nlp.visualization.controller.jersey.controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.nlp.visualization.common.CONSTANTS;
import com.nlp.visualization.core.format.FormatUtils;
import com.nlp.visualization.core.sentence.SentenceType;
import com.nlp.visualization.core.sentence.SentenceUtils;
import com.nlp.visualization.pojo.NLP.seg.SegmentEntity;
import com.nlp.visualization.pojo.NLP.sen.SentenceEntity;
import com.nlp.visualization.pojo.common.AjaxReturn;
import com.nlp.visualization.pojo.crawler.PlainHtml;
import com.nlp.visualization.service.ICrawlerService;
import com.nlp.visualization.service.IDataSentenceService;
import com.nlp.visualization.utils.ConvertUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;

import static com.nlp.visualization.common.CONSTANTS.ERROR_UPLOAD;
import static com.nlp.visualization.core.sentence.SentenceType.HANLP_MaxEnt;

@Controller("SentenceController")
@Path("/sen")
public class SentenceController {


    private Logger logger = LoggerFactory.getLogger(SentenceController.class);

    private Gson gson = new GsonBuilder().setPrettyPrinting().create();

    private SentenceType defaultType = SentenceType.HANLP_CRF;//默认一个type，如果用户不填写的话，或者填写有误的话，使用默认type

    private final String CONTENXT = CONSTANTS.CONTEXT;

    @Autowired
    private IDataSentenceService dataSentenceService;


    @Autowired
    private ICrawlerService crawlerService;

    /**
     * 单文本分析
     *
     * @param json
     * @return
     */
    @POST
    @Path("/singleness")
    @Consumes(MediaType.APPLICATION_JSON)
    public String singleSentences(String json) {

        AjaxReturn res;
        SentenceType sentenceType;
        String text;
        String type;
        String format;
        Map map;
        SentenceEntity entity;
        try {
            //从json中取值
            map = ConvertUtils.jsonToMap(json);
            text = (String) map.get("text");
            type = (String) map.get("type");
            format = (String) map.get("format");
            //看是否使用默认的词法分析类型
            if (type == null || SentenceUtils.getSentenceType(type) == null)
                sentenceType = defaultType;
            else
                sentenceType = SentenceUtils.getSentenceType(type);
            //看是否指定格式，如果不指定，则使用默认的json格式
            if (format == null)
                format = "json";
            else
                format = format.toLowerCase();
            //如果连这个字段都不填，那就直接抛出异常咯
            if (text == null)
                throw new Exception();

            //按格式返回数据
            switch (format) {
                case "json":
                    entity = dataSentenceService.parseSingle(text, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entity);
                    return gson.toJson(res);
                case "xml":
                    entity = dataSentenceService.parseSingle(text, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entity);
                    return FormatUtils.formatObj("XML", res);
                case "text":
                    List<String> list = new ArrayList<>();
                    list.add(text);
                    return dataSentenceService.parse2Text(list, sentenceType);
                default:
                    entity = dataSentenceService.parseSingle(text, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entity);
                    return gson.toJson(res);
            }

        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常", null));
        }
    }


    /**
     * 多文本分析
     *
     * @param json
     * @return
     */
    @POST
    @Path("/multiple")
    @Consumes(MediaType.APPLICATION_JSON)
    public String multiSentences(String json) {

        AjaxReturn res;
        SentenceType sentenceType;
        List<String> texts = new ArrayList<>();
        String type;
        Map map;
        String format;
        List<SentenceEntity> entities;
        try {
            //从json中取值
            map = ConvertUtils.jsonToMap(json);
            type = (String) map.get("type");
            format = (String) map.get("format");
            //看是否使用默认的词法分析类型
            if (type == null || SentenceUtils.getSentenceType(type) == null)
                sentenceType = defaultType;
            else
                sentenceType = SentenceUtils.getSentenceType(type);
            //看是否指定格式，如果不指定，则使用默认的json格式
            if (format == null)
                format = "json";
            else
                format = format.toLowerCase();
            JSONArray textArray = (JSONArray) map.get("texts");
            //如果连这个字段都不填，那就直接抛出异常咯
            if (textArray == null)
                throw new Exception();
            Iterator iterator = textArray.iterator();
            while (iterator.hasNext()) {
                JSONObject jsonObject = (JSONObject) iterator.next();
                texts.add(jsonObject.getString("text"));
            }

            //按格式返回数据
            switch (format) {
                case "json":
                    entities = dataSentenceService.parseMutil(texts, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entities);
                    return gson.toJson(res);
                case "xml":
                    entities = dataSentenceService.parseMutil(texts, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entities);
                    return FormatUtils.formatObj("XML", res);
                case "text":
                    return dataSentenceService.parse2Text(texts, sentenceType);
                default:
                    entities = dataSentenceService.parseMutil(texts, sentenceType);
                    res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", entities);
                    return gson.toJson(res);
            }
        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常", null));
        }


    }


    @POST
    @Path("/url")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public String urlSegment(String json) {
        //返回的结果
        Map<String, Object> result = new HashMap<>();
        //存储链接的集合
        List<String> urls = new ArrayList<>();
        //结果中的数据
        List<Map<String, Object>> resultSrc = new ArrayList<>();
        try {
            Map map = ConvertUtils.jsonToMap(json);
            if (map.get("urls") != null) {
                JSONArray textArray = (JSONArray) map.get("urls");
                Iterator iterator = textArray.iterator();
                while (iterator.hasNext()) {
                    JSONObject text = (JSONObject) iterator.next();
                    urls.add(text.getString("url").trim());
                }
            } else if (map.get("url") != null) {
                urls.add(map.get("url").toString());
            } else {
                throw new ParseException("参数不正确", 0);
            }
        } catch (ParseException e) {
            logger.error("传入的参数不正确");
            e.printStackTrace();
            return new Gson().toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常"));
        } catch (Exception e) {
            return new Gson().toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "未知异常"));
        }

        //开始爬虫并处理分词部分
        try {
            String[] links = new String[urls.size()];
            for (int i = 0; i < urls.size(); i++) {
                links[i] = urls.get(i);
            }
            //将爬取下来的网站存储在list中
            List<File> fileList = crawlerService.crawlAsFiles(links);
            //将文本进行分词
            Iterator<File> iterator = fileList.iterator();
            while (iterator.hasNext()) {
                File tmpFile = iterator.next();
                try {
                    //新建结果Map
                    Map<String, Object> dataMap = new HashedMap();
                    //读文件
                    String fileSttring = FileUtils.readFileToString(tmpFile);
                    //提取content部分
                    PlainHtml html = gson.fromJson(fileSttring, PlainHtml.class);
                    fileSttring = html.getContent().trim();
                    //句法分析1,这里分析的结果用于返回给前端展示
                    SentenceEntity sentenceEntity = dataSentenceService.parseSingle(fileSttring, HANLP_MaxEnt);
                    //句法分析2,保存到指定路径，这里分析的结果用于提供给用户下载查看
                    File afterSenFile = dataSentenceService.parseFile(tmpFile, CONTENXT, HANLP_MaxEnt);
                    //添加进结果
                    dataMap.put("fileName", tmpFile.getName());
                    dataMap.put("senResult", sentenceEntity);
                    dataMap.put("txt", fileSttring);
                    dataMap.put("download", afterSenFile.getPath().split(CONTENXT + "/")[1]);
                    resultSrc.add(dataMap);

                    logger.info("成功解析URL的文件：" + tmpFile.getName());
                } catch (IOException e) {
                    return IOExcepction(e, result);
                }

            }
            result.put("status", 0);
            result.put("msg", "上传成功");
            result.put("data", resultSrc);

            return gson.toJson(result);

        } catch (Exception e) {
            return new Gson().toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "未知异常"));
        }

    }

    private String IOExcepction(IOException e, Map<String, Object> result) {
        result.put("status", ERROR_UPLOAD);
        result.put("msg", "上传异常");
        logger.error("上传异常");
        e.printStackTrace();
        return gson.toJson(result);
    }

}
